"""
作用域演示

四种作用域：
L（Local）：最内层，包含局部变量，比如一个函数/方法内部。
E（Enclosing）：包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数，一个函数（或类） A 里面又包含了一个函数 B ，那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
G（Global）：当前脚本的最外层，比如当前模块的全局变量。
B（Built-in）： 包含了内建的变量/关键字等，最后被搜索。
"""

# 全局变量
total = 0


def sum1(num1: int, num2: int):
    # total在这里是局部变量
    total = num1 + num2
    print("函数内是局部变量 : ", total)
    return total


# global  示例
def sum2(num1: int, num2: int):
    global total  # 使用 global 关键字声明使用外层的全局变量
    total = num1 + num2
    print("使用的是全局变量 : ", total)
    return total


#  nonlocal关键字 示例
def sum3():
    to1 = 0

    def inner_sum(num1: int, num2: int):
        # to1在这里是内部函数的局部变量
        nonlocal to1  # 使用 nonlocal 关键字声明 使用外层的局部变量
        to1 = num1 + num2

    inner_sum(2, 3)
    print("使用的是全局变量 : ", to1)


# 关于与Java作用域一些对比
def sum4(num1: int, num2: int):
    t1 = num1 + num2
    if True:
        t2 = t1  # 变量t2 属于整个函数的作用域，与Java有很大区别，在外层也可访问
    return t2


a = 10

# 不宜察觉的错误示例
def m1():
    # 这里编译报错，因为通过“a=b”定义了局部变量a，但是局部变量a在前一句“b=a+1”中被引用了，也就是说先使用，然后才定义的，
    # 这里的“b=a+1”中a被解析成了局部变量，然而a并未定义，所以导致错误
    b = a + 1
    a = b
    print(b)


if __name__ == '__main__':

    #全局变量未启作用，函数内重新声明了一个total局部变量，赋值操作也是对局部变量的赋值
    sum1(1, 2)
    print(f'全局变量 total={total}')

    #global  示例
    sum2(1, 2)
    print(f'全局变量 total={total}')

    # nonlocal关键字 示例
    sum3()

    # 函数的变量作用域示例
    print(f'sum4 = {sum4(1, 11)}')

    #不宜察觉的错误示例
    m1()
